package com.leinao.util.sha;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 
 * RSA加密算法
 * 
 * @author wangshoufa 
 * @date 2019年3月15日 下午5:15:50
 *
 */
public class RSAUtil {

	private static final Logger log = LoggerFactory.getLogger(RSAUtil.class);

	/** 私钥 */
	private static RSAPrivateKey prk;

	/** 公钥 */
	private static RSAPublicKey pbk;

	static {
		InputStream in = null;
		/** 一、初始化私钥 */
		try {
			in = RSAUtil.class.getResourceAsStream("/keypair/Skey_RSA_priv_for_web.dat");// 从类路径加载
			ObjectInputStream b = new ObjectInputStream(in);
			prk = (RSAPrivateKey) b.readObject();
			log.debug("rsa priKey: {}", prk);
		} catch (FileNotFoundException e) {
			log.error("FileNotFoundException", e);
		} catch (IOException e) {
			log.error("IOException", e);
		} catch (ClassNotFoundException e) {
			log.error("ClassNotFoundException" + e);
		} finally {
			try {
				if (in != null) {
					in.close();
					in = null;
				}
			} catch (IOException e) {
				log.error("IOException", e);
			}
		}
		/** 初始化公钥 */
		try {
			in = RSAUtil.class.getResourceAsStream("/keypair/Skey_RSA_pub_for_web.dat");// 从类路径加载
			ObjectInputStream b = new ObjectInputStream(in);
			pbk = (RSAPublicKey) b.readObject();
			log.debug("rsa pubKey: {}", pbk);
		} catch (FileNotFoundException e) {
			log.error("FileNotFoundException", e);
		} catch (IOException e) {
			log.error("IOException", e);
		} catch (ClassNotFoundException e) {
			log.error("ClassNotFoundException", e);
		} finally {
			try {
				if (in != null) {
					in.close();
					in = null;
				}
			} catch (IOException e) {
				log.error("IOException", e);
			}
		}
	}

	/**
	 * 根据指定的私钥解密JS加密的密文
	 * 
	 * @throws UnsupportedEncodingException
	 * @return 返回明文
	 */
	public static String decText(byte[] ctext) throws UnsupportedEncodingException {
		BigInteger c = new BigInteger(ctext);
		BigInteger d = prk.getPrivateExponent();
		// 获取私钥参数及解密
		BigInteger n = prk.getModulus();
		BigInteger m = c.modPow(d, n);
		// 显示解密结果
		byte[] mt = m.toByteArray();
		String text = new String(mt, "utf-8");
		StringBuffer sb = new StringBuffer(text);

		return sb.reverse().toString();
	}

	/**
	 * 
	 * @return 返回公钥的16进制模数
	 */
	public static String getPubModulus() {
		BigInteger n = pbk.getModulus();
		log.debug("getModulus: {}", n);
		return n.toString(16);
	}

	/**
	 * 
	 * @return 返回公钥的指数
	 */
	public static String getPubExponent() {
		BigInteger e = pbk.getPublicExponent();
		log.debug("getPublicExponent: {}", e);
		return e.toString(16);
	}

	public static String encrypt( String str) throws Exception{
		//RSA加密
		StringBuffer buffer = new StringBuffer(str);
		BigInteger e = pbk.getPublicExponent();
		BigInteger n = pbk.getModulus();
		// 获取明文m
		byte ptext[] = buffer.reverse().toString().getBytes();
		BigInteger m = new BigInteger(ptext);
		// 计算密文c
		BigInteger c = m.modPow(e, n);
		return c.toString(16);
	}
	/**
	 * 密码解密
	 * 
	 * @param password
	 * @return
	 */
	public static String decPassWord(String password) {
		try {
			StringBuilder buf = new StringBuilder();
			String[] segments = password.split(" ");
			for (String segment : segments) {
				buf.append(RSAUtil.decText(new BigInteger(segment, 16).toByteArray()));
			}
			return buf.toString();
		} catch (Exception e) {
			log.error("decrypt with RSA exception.", e);
			return "";
		}
	}

	public static void main(String[] args) throws Exception {
		String message = encrypt("14##_e2012f1879af46e68714f098a59e7cea");


		// 计算密文c
		System.out.println("随机生成的公钥为:" +message  );

		System.out.println("随机生成的私钥为:" + decPassWord(message));
	}
}
